<template>
  <span>{{ displayValue }}</span>
</template>

<script>
export default {
  name: 'CountTo',
  props: {
    startVal: {
      type: Number,
      default: 0
    },
    endVal: {
      type: Number,
      required: true
    },
    duration: {
      type: Number,
      default: 2000
    },
    decimal: {
      type: Number,
      default: 0
    },
    separator: {
      type: String,
      default: ''
    },
    prefix: {
      type: String,
      default: ''
    },
    suffix: {
      type: String,
      default: ''
    },
    autoplay: {
      type: Boolean,
      default: true
    }
  },
  data() {
    return {
      displayValue: this.formatValue(this.startVal),
      localStartVal: this.startVal,
      printVal: null,
      animationFrame: null,
      start: null,
      remaining: null,
      localDuration: this.duration,
      isAnimating: false
    }
  },
  computed: {
    countDown() {
      return this.startVal > this.endVal
    }
  },
  watch: {
    autoplay: {
      handler(newValue) {
        if (newValue) {
          this.startFunc();
        }
      },
      immediate: true
    },
    startVal() {
      this.localStartVal = this.startVal;
      this.displayValue = this.formatValue(this.startVal);
    },
    endVal() {
      this.isAnimating = false;
      this.startFunc();
    }
  },
  mounted() {
    if (this.autoplay) {
      this.startFunc();
    }
  },
  beforeUnmount() {
    this.reset();
  },
  methods: {
    startFunc() {
      this.isAnimating = true;
      this.reset();
      this.localStartVal = this.startVal;
      
      if (this.startVal === this.endVal) {
        this.displayValue = this.formatValue(this.endVal);
        return;
      }
      
      this.printVal = this.startVal;
      this.remaining = this.localDuration;
      
      // 开始动画
      this.animationId = requestAnimationFrame(this.animate);
    },
    animate(timestamp) {
      if (!this.start) {
        this.start = timestamp;
      }
      
      const progress = timestamp - this.start;
      this.remaining = this.localDuration - progress;
      
      // 进度计算
      if (this.countDown) {
        this.printVal = this.localStartVal - ((this.localStartVal - this.endVal) * (progress / this.localDuration));
      } else {
        this.printVal = this.localStartVal + ((this.endVal - this.localStartVal) * (progress / this.localDuration));
      }
      
      // 确保不超过目标值
      if (this.countDown) {
        this.printVal = this.printVal < this.endVal ? this.endVal : this.printVal;
      } else {
        this.printVal = this.printVal > this.endVal ? this.endVal : this.printVal;
      }
      
      // 更新显示值
      this.displayValue = this.formatValue(this.printVal);
      
      // 动画完成或继续
      if (progress < this.localDuration) {
        this.animationId = requestAnimationFrame(this.animate);
      } else {
        this.isAnimating = false;
        this.displayValue = this.formatValue(this.endVal);
      }
    },
    reset() {
      if (this.animationId) {
        cancelAnimationFrame(this.animationId);
        this.animationId = null;
      }
      this.start = null;
    },
    formatValue(val) {
      // 格式化数字
      let formattedValue = parseFloat(val).toFixed(this.decimal);
      
      // 处理千分位分隔符
      // if (this.separator) {
      //   const parts = formattedValue.toString().split('.');
      //   parts[0] = parts[0].replace(/\B(?=(\d{3})+(?!\d))/g, this.separator);
      //   formattedValue = parts.join('.');
      // }
      
      // 添加前缀和后缀
      return this.prefix + formattedValue + this.suffix;
    }
  }
}
</script>

<style scoped>
/* 可以添加样式 */
</style> 